package com.woniuxy.micropermissionserver.permissionmanage.service.impl;

import com.woniuxy.microcommonserver.bean.permission_hcz.Admin;
import com.woniuxy.microcommonserver.bean.permission_hcz.Permission;
import com.woniuxy.micropermissionserver.permissionmanage.mapper.PermissionMapper;
import com.woniuxy.micropermissionserver.permissionmanage.service.IPermissionService;
import com.woniuxy.micropermissionserver.vo.MetaVo;
import com.woniuxy.micropermissionserver.vo.RouterVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

@Service
@Transactional(readOnly = true)
public class PermissionServiceImpl implements IPermissionService {

    @Resource
    private PermissionMapper permissionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void savePermission(Permission permission) {
        permissionMapper.savePermission(permission);
    }

    @Override
    public List<String> findPermsByAdmin(Admin admin) {
        return permissionMapper.findPermsByAdmin(admin);
    }

    @Override
    public List<Permission> findPermissionTreeByAdminId(Integer adminId) {
        List<Permission> permissions = permissionMapper.findPermissionTreeByAdminId(adminId);
        return getChildPermissions(permissions, 0);
    }

    @Override
    public List<RouterVo> buildMenus(List<Permission> permissions) {
        List<RouterVo> routers = new LinkedList<>();
        for (Permission p : permissions) {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setName(getRoutName(p));
            router.setPath(getRouterPath(p));
            router.setComponent(getComponent(p));
            router.setMeta(new MetaVo(p.getName(), p.getIcon(), false));
            List<Permission> childList = p.getChildren();
            if (!childList.isEmpty() && childList.size() > 0 && "M".equals(p.getType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildMenus(childList));
            } else if (isMenuFrame(p)) {
                List<RouterVo> childRouters = new ArrayList<>();
                RouterVo child = new RouterVo();
                child.setPath(p.getPath());
                child.setComponent(p.getComponent());
                child.setName(StringUtils.capitalize(p.getPath()));
                child.setMeta(new MetaVo(p.getName(), p.getIcon(), false));
                childRouters.add(child);
                router.setChildren(childRouters);
            }
            routers.add(router);
        }
        return routers;
    }

    private String getComponent(Permission p) {
        String component = "Layout";
        if (StringUtils.isNotEmpty(p.getComponent()) && !isMenuFrame(p)) {
            component = p.getComponent();
        } else if (StringUtils.isEmpty(p.getComponent()) && isParentView(p))
        {
            component = "ParentView";
        }
        return component;
    }

    private boolean isParentView(Permission p) {
        return p.getPid().intValue() != 0 && "M".equals(p.getType());
    }

    private String getRouterPath(Permission p) {
        String routerPath = p.getPath();
        // 非外链并且是一级目录（类型为目录）
        if (0 == p.getPid().intValue() && "M".equals(p.getType())) {
            routerPath = "/" + p.getPath();
        }
        // 非外链并且是一级目录（类型为菜单）
        else if (isMenuFrame(p)) {
            routerPath = "/";
        }
        return routerPath;
    }

    private String getRoutName(Permission p) {
        String routeName = StringUtils.capitalize(p.getPath());
        if (isMenuFrame(p)) {
            routeName = StringUtils.EMPTY;
        }
        return routeName;
    }

    private boolean isMenuFrame(Permission p) {
        return p.getPid().intValue() == 0 && "C".equals(p.getType());
    }

    private List<Permission> getChildPermissions(List<Permission> permissions, int pid) {
        List<Permission> permissionList = new ArrayList<>();
        for (Iterator<Permission> iterator = permissions.listIterator(); iterator.hasNext();) {
            Permission p = iterator.next();
            if (p.getPid() == pid) {
                recursionFunction(permissions, p);
                permissionList.add(p);
            }
        }
        return permissionList;
    }

    private void recursionFunction(List<Permission> permissions, Permission p) {

        List<Permission> childList =getChildList(permissions, p);
        p.setChildren(childList);
        childList.forEach(c -> {
            if (hasChild(permissions, c)) {
                recursionFunction(permissions, c);
            }
        });
    }

    private boolean hasChild(List<Permission> permissions, Permission c) {
        return !getChildList(permissions, c).isEmpty();
    }

    private List<Permission> getChildList(List<Permission> permissions, Permission p) {
        List<Permission> childList = new ArrayList<>();
        permissions.forEach(c -> {
            if (c.getPid().intValue() == p.getId().intValue()) {
                childList.add(c);
            }
        });
        return childList;
    }
}
